﻿using FinalPointSet.Model.Model.FieldMapping;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;

namespace FinalPointSet.Model.Model
{
    /// <summary>
    /// 数据源映射规则
    /// </summary>
    public class DataSourceMappingRule
    {
        /// <summary>
        /// 排序
        /// </summary>
        public int Sequence { get; set; } = 0;
        /// <summary>
        /// 来源数据源
        /// </summary>
        public DataSource SourceDataSource { get; set; } = new();
        /// <summary>
        /// 目标数据源
        /// </summary>
        public DataSource TargetDataSource { get; set; } = new();
        /// <summary>
        /// 字段类型映射
        /// </summary>
        public ObservableCollection<FieldMappingKeyValuePair> FieldTypeMapping { get; set; } = new();
    }

    /// <summary>
    /// 数据源映射规则序列化转换器
    /// </summary>
    public class DataSourceMappingRuleConverter : JsonConverter<DataSourceMappingRule>
    {
        private List<DataSource> dataSources = [];
        public DataSourceMappingRuleConverter() { }
        public DataSourceMappingRuleConverter(List<DataSource> dataSources)
        {
            this.dataSources = dataSources;
        }
        public override void WriteJson(JsonWriter writer, DataSourceMappingRule? value, JsonSerializer serializer)
        {
            if (value == null) throw new ArgumentNullException(nameof(value));
            //只序列化Name属性
            JObject obj = new()
            {
                { "Sequence", value.Sequence },
                { "SourceDataSource", value.SourceDataSource.Name },
                { "TargetDataSource", value.TargetDataSource.Name },
                { "FieldTypeMapping", JArray.FromObject(value.FieldTypeMapping, serializer) }
            };
            obj.WriteTo(writer);
        }

        public override DataSourceMappingRule ReadJson(JsonReader reader, Type objectType, DataSourceMappingRule? existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            var obj = JObject.Load(reader);
            return Parse(obj, serializer, dataSources);
        }

        public static DataSourceMappingRule Parse(JObject jsonObj, JsonSerializer serializer, List<DataSource> dataSources)
        {
            DataSourceMappingRule result = new()
            {
                SourceDataSource = new DataSource(),
                TargetDataSource = new DataSource()
            };
            // 反序列化 FieldTypeMapping
            if (jsonObj["Sequence"] is JToken jtSequence)
            {
                result.Sequence = int.Parse(jtSequence.ToString());
            }

            // 反序列化 FieldTypeMapping
            if (jsonObj["FieldTypeMapping"] is JArray fieldTypeMappingArray)
            {
                result.FieldTypeMapping = fieldTypeMappingArray.ToObject<ObservableCollection<FieldMappingKeyValuePair>>(serializer) ?? new ObservableCollection<FieldMappingKeyValuePair>();
            }

            // 反序列化 SourceDataSource 的 Name 属性
            if (jsonObj["SourceDataSource"] is JToken sourceDataSource)
            {
                string name = sourceDataSource.ToString();
                // 反序列化 SourceDataSource 的 Name 属性
                result.SourceDataSource.Name = name;

                if (dataSources != null && dataSources.Count > 0)
                {
                    DataSource dataSource = dataSources.FirstOrDefault(d => d.Name.Equals(name), new DataSource());
                    result.SourceDataSource.LogoPath = dataSource.LogoPath;
                    result.SourceDataSource.Sequence = dataSource.Sequence;
                }

            }
            // 反序列化 TargetDataSource 的 Name 属性
            if (jsonObj["TargetDataSource"] is JToken targetDataSource)
            {
                string name = targetDataSource.ToString();
                // 反序列化 targetDataSource 的 Name 属性
                result.TargetDataSource.Name = name;

                if (dataSources != null && dataSources.Count > 0)
                {
                    DataSource dataSource = dataSources.FirstOrDefault(d => d.Name.Equals(name), new DataSource());
                    result.TargetDataSource.LogoPath = dataSource.LogoPath;
                    result.TargetDataSource.Sequence = dataSource.Sequence;
                }

            }
            return result;
        }
    }
}
